package com.zlkj.sms.util;

import com.zlkj.sms.bean.DeviceBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author lzw
 * @description 视频预览webSocket
 * @date 2021/1/21
 */
@Slf4j
@ServerEndpoint("/sms/play/{serialId}")
@Component
public class VideoPlayWebSocket {

    private ThreadPoolTaskExecutor taskExecutor = (ThreadPoolTaskExecutor) AppBeanTools.getBean("playTaskExecutor");

    /**
     * webSocket会话集
     */
    private static ConcurrentHashMap<String, VideoPlayWebSocket> webSocketMap = new ConcurrentHashMap<>();

    /**
     * 会话
     */
    private Session session;

    /**
     * 会话标识
     */
    private String serialId = "";

    /**
     * 在线消费者数量
     */
    public static int count = 0;

    /**
     * 连接建立
     * @param session
     * @param serialId
     */
    @OnOpen
    public void onOpen(Session session,@PathParam("serialId") String serialId) {
        this.session = session;
        this.serialId = serialId;
        if(webSocketMap.containsKey(serialId)){
            webSocketMap.remove(serialId);
            webSocketMap.put(serialId, this);
        }else{
            webSocketMap.put(serialId, this);
        }

        addCount();

        //连接成功后开始推流
        DeviceBean device = Tools.getDeviceInfo(serialId);
        if(device != null){
            VideoPlay video = new VideoPlay(device.getStreamUrl(), serialId, device.getWidth(), device.getHeight());
            taskExecutor.submit(video);
            //添加推流线程
            PushStreamTools.addVideo(serialId, video);
        }else{
            sendMessage("设备【" + serialId + "】未找到");
        }
    }

    /**
     * 连接关闭
     */
    @OnClose
    public void onClose() {
        if(webSocketMap.containsKey(serialId)){
            webSocketMap.remove(serialId);
        }

        subCount();

        //移除并结束推流线程
        PushStreamTools.removeVideo(serialId);
    }

    /**
     * 连接错误
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    /**
     * 发送消息
     * @param text
     */
    public void sendMessage(String text){
        try {
            this.session.getBasicRemote().sendText(text);
        } catch (IOException e) {
            log.error("发送消息异常：{}", e.getMessage());
        }
    }

    /**
     * 根据会话标识给指定消费者发送消息
     * @param serialId
     * @param text
     */
    public static void sendMessage(String serialId, String text){
        try {
            VideoPlayWebSocket ws = webSocketMap.get(serialId);
            if(ws != null && ws.session != null){
                ws.session.getBasicRemote().sendText(text);
            }
        } catch (IOException e) {
            log.error("向web窗口" + serialId + "发送消息异常：{}", e.getMessage());
        }
    }

    public static synchronized void addCount(){
        count++;
    }

    public static synchronized void subCount(){
        count--;
    }
}
